package cn.com.hbhgkj.webapp.taglib;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

import javax.servlet.jsp.JspException;

import org.apache.struts2.views.jsp.ui.SelectTag;

import cn.com.hbhgkj.model.LabelValue;

import com.opensymphony.xwork2.ActionContext;

public class CountryTag extends SelectTag {

	public int doStartTag() throws JspException {
		List<LabelValue> targetList = buildCountryList(pageContext.getRequest().getLocale());
		ActionContext.getContext().getValueStack()
				.set("crs_countrys", targetList);
		this.setList("%{crs_countrys}");
		return super.doStartTag();
	}

	/**
	 * Build a List of LabelValues for all the available countries. Uses the two
	 * letter uppercase ISO name of the country as the value and the localized
	 * country name as the label.
	 * 
	 * @param locale
	 *            The Locale used to localize the country names.
	 * 
	 * @return List of LabelValues for all available countries.
	 */
	@SuppressWarnings("unchecked")
	protected List<LabelValue> buildCountryList(Locale locale) {
		final Locale[] available = Locale.getAvailableLocales();

		List<LabelValue> countries = new ArrayList<LabelValue>();

		for (Locale anAvailable : available) {
			final String iso = anAvailable.getCountry();
			final String name = anAvailable.getDisplayCountry(locale);

			if (!"".equals(iso) && !"".equals(name)) {
				LabelValue country = new LabelValue(name, iso);

				if (!countries.contains(country)) {
					countries.add(new LabelValue(name, iso));
				}
			}
		}

		Collections.sort(countries, new LabelValueComparator(locale));

		return countries;
	}

	/**
	 * Class to compare LabelValues using their labels with locale-sensitive
	 * behaviour.
	 */
	public class LabelValueComparator implements Comparator {
		private Comparator c;

		/**
		 * Creates a new LabelValueComparator object.
		 * 
		 * @param locale
		 *            The Locale used for localized String comparison.
		 */
		public LabelValueComparator(final Locale locale) {
			c = Collator.getInstance(locale);
		}

		/**
		 * Compares the localized labels of two LabelValues.
		 * 
		 * @param o1
		 *            The first LabelValue to compare.
		 * @param o2
		 *            The second LabelValue to compare.
		 * 
		 * @return The value returned by comparing the localized labels.
		 */
		@SuppressWarnings("unchecked")
		public final int compare(Object o1, Object o2) {
			LabelValue lhs = (LabelValue) o1;
			LabelValue rhs = (LabelValue) o2;

			return c.compare(lhs.getLabel(), rhs.getLabel());
		}
	}
}
